#include "Channel.h"
#include <sys/epoll.h>
#include"EventLoop.h"
#include"Logger.h"
const int Channel::kNoneEvent = 0; // 对任何事件都不感兴趣
// PRI是紧急事件
const int Channel::kReadEvent = EPOLLIN | EPOLLPRI; // 对读事件
const int Channel::kWriteEvent = EPOLLOUT;

// 每一个Channel所属一个Loop，并且有一个唯一的fd，因为多线程模式，而不是多进程
Channel::Channel(EventLoop *loop, int fd)
    : loop_(loop), fd_(fd), events_(0), revents_(0), index_(-1), tied_(false)
{
}
Channel::~Channel()
{
    // 判断是否是在当前的事件循，并且是否是我这个事件循环的
    // 但是我不写
}


// 观察者，观察一个强智能指针
void Channel::tie(const std::shared_ptr<void>& obj)
{
    tie_ = obj;
    tied_ = true;
}

// 更新底层红黑树对应节点的关心事件，更改poller里面响应的事件
// EventLoop => ChannelList  Poller 
// 为什么 从文件描述符找到Channel用列表？
void Channel::update()
{
    // 通过Channel 找到 EventLoop。找到Poller 调用对应的事件
    // add code...
    loop_->updateChannel(this);
}

// 在channel所属的EventLoop，把当前的channel删除掉
void Channel::remove()
{
    // add code
    loop_->removeChannel(this);
}

// fd得到poller通知以后处理事件的。
// 成员变量tied_ 主要就是判断Channel是否又被tied_ 过，以及是否正在被tied_
void Channel::handlerEvent(Timestamp receiveTime)
{
    // 判断TcpConnction是否有断开连接
    std::shared_ptr<void> guard;
    if(tied_)
    {
        guard = tie_.lock();// 将弱指针提升，返回值不为NULL表示成功
        if(guard)
        {
            handlerEventWithGuard(receiveTime);
        }
    }
    else
    {
        handlerEventWithGuard(receiveTime);
    }
}

// 根据poller通知的channel发生的具体事件，由channel执行对应的回调方法。
void Channel::handlerEventWithGuard(Timestamp receiveTime)
{
    LOG_INFO("channel handlerEvent revents:%d\n",revents_);
    if((revents_ & EPOLLHUP) && !(revents_ & EPOLLIN))
    {
        if(closeCallback_)
        {
            closeCallback_();
        }
    }

    if(revents_ & EPOLLERR)
    {
        if(errorCallback_)
        {
            errorCallback_();
        }
    }

    if(revents_& (EPOLLIN | EPOLLPRI))
    {
        //可读事件
        if(readCallback_)
        {
            readCallback_(receiveTime);
        }
    }
    if(revents_ & EPOLLOUT)
    {
        if(writeCallback_)
        {
            writeCallback_();
        }
    }
}
